package com.current.game.two;

import javax.swing.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

/**
 * @author baopan
 * @createTime 2024/5/12 22:31
 */
public class TTFFrame {
    // 游戏板尺寸、方块大小等
    private static final int BOARD_SIZE = 4;
    private static final int TILE_SIZE = 100;

    public void get2048Frame() {
        System.out.println("====>get2048Frame");
        JFrame frame = new JFrame("2048 Game");
        // 设置窗口大小不可变
//        frame.setResizable(false);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(BOARD_SIZE * TILE_SIZE + 17, BOARD_SIZE * TILE_SIZE + 40);

        int[][] ttfJValue = new int[4][4];
        doRandom(ttfJValue);
        TTFJpanel ttfJpanel = new TTFJpanel(ttfJValue);
//        ttfJpanel.requestFocusInWindow(); // 请求焦点
//        ttfJpanel.requestFocus();
        ttfJpanel.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                int keyCode = e.getKeyCode();
                System.out.println("===>key:" + keyCode);

                // 你可以在这里添加额外的逻辑来处理特定的按键事件
                switch (keyCode) {
                    case 38://上
                    case 87://w
                        doUp(ttfJValue);
                        break;
                    case 40://下
                    case 83://s
                        doDown(ttfJValue);
                        break;
                    case 37://左
                    case 65://a
                        doLeft(ttfJValue);
                        break;
                    case 39://右
                    case 68://d
                        doRight(ttfJValue);
                        break;
                    default:
                        break;
                }
                ttfJpanel.repaint();
            }

            private void doUp(int[][] ttfJValue) {
                int[][] temps = copyTTFValue(ttfJValue);
                doCalValues(ttfJValue, 0, 0, 0, 3);
                doCalValues(ttfJValue, 1, 0, 1, 3);
                doCalValues(ttfJValue, 2, 0, 2, 3);
                doCalValues(ttfJValue, 3, 0, 3, 3);

                boolean self = isSelf(ttfJValue, temps);
                if (!self) {
                    doRandom(ttfJValue);
                }
            }

            private void doDown(int[][] ttfJValue) {
                int[][] temps = copyTTFValue(ttfJValue);
                doCalValues(ttfJValue, 0, 3, 0, 0);
                doCalValues(ttfJValue, 1, 3, 1, 0);
                doCalValues(ttfJValue, 2, 3, 2, 0);
                doCalValues(ttfJValue, 3, 3, 3, 0);

                boolean self = isSelf(ttfJValue, temps);
                if (!self) {
                    doRandom(ttfJValue);
                }
            }


            private void doLeft(int[][] ttfJValue) {//
                int[][] temps = copyTTFValue(ttfJValue);
                doCalValues(ttfJValue, 0, 0, 3, 0);
                doCalValues(ttfJValue, 0, 1, 3, 1);
                doCalValues(ttfJValue, 0, 2, 3, 2);
                doCalValues(ttfJValue, 0, 3, 3, 3);

                boolean self = isSelf(ttfJValue, temps);
                if (!self) {
                    doRandom(ttfJValue);
                }
            }

            private void doRight(int[][] ttfJValue) {//
                int[][] temps = copyTTFValue(ttfJValue);
                doCalValues(ttfJValue, 3, 0, 0, 0);
                doCalValues(ttfJValue, 3, 1, 0, 1);
                doCalValues(ttfJValue, 3, 2, 0, 2);
                doCalValues(ttfJValue, 3, 3, 0, 3);

                boolean self = isSelf(ttfJValue, temps);
                if (!self) {
                    doRandom(ttfJValue);
                }
            }

            private boolean isSelf(int[][] ttfJValue, int[][] originValue) {
                for (int i = 0; i < 4; i++) {
                    for (int j = 0; j < 4; j++) {
                        if (ttfJValue[i][j] != originValue[i][j]) {
                            return false;
                        }
                    }
                }
                return true;
            }

            private int[][] copyTTFValue(int[][] ttfJValue) {
                int[][] result = new int[4][4];
                for (int i = 0; i < 4; i++) {
                    for (int j = 0; j < 4; j++) {
                        result[i][j] = ttfJValue[i][j];
                    }
                }
                return result;
            }

            private void doRandom(int[][] ttfJValue) {
                int random = new Random().nextInt(16);
                int zeroCount = 0;
                while (true) {
                    boolean hasEmpty = false;
                    for (int i = 0; i < 4; i++) {
                        for (int j = 0; j < 4; j++) {
                            if (ttfJValue[i][j] == 0) {
                                hasEmpty = true;
                                if (zeroCount == random) {
                                    ttfJValue[i][j] = 2;
                                    return;
                                }
                                zeroCount++;
                            }
                        }
                    }
                    if (!hasEmpty) {
                        return;
                    }
                }

            }

            private void doCalValues(int[][] values, int startI, int startJ, int endI, int endJ) {
                if (startI == endI) {
                    if (startJ < endJ) {//向下
                        int[] temps = mergeAndSort(values[startI][0], values[startI][1], values[startI][2], values[startI][3]);
                        values[startI][0] = temps[0];
                        values[startI][1] = temps[1];
                        values[startI][2] = temps[2];
                        values[startI][3] = temps[3];
                    } else {//向上
                        int[] temps = mergeAndSort(values[startI][3], values[startI][2], values[startI][1], values[startI][0]);
                        values[startI][3] = temps[0];
                        values[startI][2] = temps[1];
                        values[startI][1] = temps[2];
                        values[startI][0] = temps[3];
                    }
                    return;
                }
                if (startJ == endJ) {
                    if (startI < endI) {//向左
                        int[] temps = mergeAndSort(values[0][startJ], values[1][startJ], values[2][startJ], values[3][startJ]);
                        values[0][startJ] = temps[0];
                        values[1][startJ] = temps[1];
                        values[2][startJ] = temps[2];
                        values[3][startJ] = temps[3];
                    } else {//向右
                        int[] temps = mergeAndSort(values[3][startJ], values[2][startJ], values[1][startJ], values[0][startJ]);
                        values[3][startJ] = temps[0];
                        values[2][startJ] = temps[1];
                        values[1][startJ] = temps[2];
                        values[0][startJ] = temps[3];
                    }
                    return;
                }
            }

            private int[] mergeAndSort(int one, int two, int third, int four) {
                int[] column = new int[]{one, two, third, four};

                for (int i = 0; i < 4 - 1; i++) {
                    if (column[i] == column[i + 1]) {
                        column[i] *= 2; // 合并相同的数字
                        column[i + 1] = 0; // 将下一个位置设置为0，表示已经合并

                    }
                }

                // 将非零元素向左滑动
                int j = 0;
                for (int i = 0; i < 4; i++) {
                    if (column[i] != 0) {
                        column[j++] = column[i];
                    }
                }

                // 将剩余位置填充为0（如果需要）
                while (j < 4) {
                    column[j++] = 0;
                }

                return column;
            }
        });

        frame.getContentPane().add(ttfJpanel); // 添加游戏面板到JFrame
        frame.setVisible(true);
        ttfJpanel.requestFocus(true);

    }

    private void doRandom(int[][] ttfJValue) {
        int random = new Random().nextInt(16);
        int zeroCount = 0;
        while (true) {
            boolean hasEmpty = false;
            for (int i = 0; i < 4; i++) {
                for (int j = 0; j < 4; j++) {
                    if (ttfJValue[i][j] == 0) {
                        hasEmpty = true;
                        if (zeroCount == random) {
                            ttfJValue[i][j] = 2;
                            return;
                        }
                        zeroCount++;
                    }
                }
            }
            if (!hasEmpty) {
                return;
            }
        }

    }


}
